<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>多策略仿真实时展示</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        body { font-family: Arial, sans-serif; padding: 20px; max-width: 1000px; margin: auto; }
        label { display: block; margin-top: 15px; }
        input[type="text"], input[type="number"] { width: 100%; padding: 8px; margin-top: 5px; }
        button { margin-top: 15px; padding: 10px 20px; font-size: 16px; cursor: pointer; margin-right: 10px; }
        #status { margin-top: 10px; color: green; }
        canvas { background: #f9f9f9; border: 1px solid #ccc; margin-top: 30px; }
    </style>
</head>
<body>
<h2>多策略仿真实时展示</h2>

<button id="createTotalBtn">创建新的仿真记录</button>
<div id="createResult" style="margin-top:10px;"></div>

<label for="envParamIdInput">环境ID:</label>
<input type="number" id="envParamIdInput" placeholder="env_param_id" />

<label for="simulationNameInput">仿真名称：</label>
<input type="text" id="simulationNameInput" placeholder="请输入仿真名称" />

<label for="simulationIdInput">仿真ID（由后端生成）:</label>
<input type="number" id="simulationIdInput" placeholder="simulation_id" readonly />

<label for="strategySelect">选择策略：</label>
<select id="strategySelect">
    <option value="simple">策略 simple</option>
    <option value="a2c">策略 a2c</option>
    <option value="dqn">策略 dqn</option>
    <option value="ppo">策略 ppo</option>
</select>

<button id="startSimulationBtn">开始仿真运行</button>

<div id="status"></div>

<canvas id="simulationChart" width="1000" height="400"></canvas>

<script>
    const createTotalBtn = document.getElementById('createTotalBtn');
    const createResultDiv = document.getElementById('createResult');
    const envParamIdInput = document.getElementById('envParamIdInput');
    const simulationNameInput = document.getElementById('simulationNameInput');
    const simulationIdInput = document.getElementById('simulationIdInput');
    const startSimulationBtn = document.getElementById('startSimulationBtn');
    const strategySelect = document.getElementById('strategySelect');
    const statusDiv = document.getElementById('status');
    const ctx = document.getElementById('simulationChart').getContext('2d');

    const strategyConfig = {
        simple: { labelPrefix: "simple", colorSet: ['blue', 'red', 'orange'] },
        a2c: { labelPrefix: "a2c", colorSet: ['green', 'brown', 'gold'] },
        dqn: { labelPrefix: "dqn", colorSet: ['purple', 'darkred', 'darkorange'] },
        ppo: { labelPrefix: "ppo", colorSet: ['black', 'gray', 'pink'] }
    };

    let simulationChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: [],
            datasets: []
        },
        options: {
            responsive: true,
            scales: {
                x: { title: { display: true, text: '时间点' } },
                y: { title: { display: true, text: '数值' }, beginAtZero: true }
            }
        }
    });

    function ensureDatasets(simulationType) {
        const config = strategyConfig[simulationType];
        if (!config) return;

        const prefix = config.labelPrefix;
        const colors = config.colorSet;

        const existing = simulationChart.data.datasets.filter(ds => ds.label.startsWith(prefix));
        if (existing.length > 0) return;

        simulationChart.data.datasets.push(
            { label: `${prefix} Battery Energy`, data: [], borderColor: colors[0], fill: false, tension: 0.1 },
            { label: `${prefix} Grid Power`, data: [], borderColor: colors[1], fill: false, tension: 0.1 },
            { label: `${prefix} Solar Power`, data: [], borderColor: colors[2], fill: false, tension: 0.1 }
        );
    }

    createTotalBtn.onclick = async () => {
        const envParamId = envParamIdInput.value.trim();
        const name = simulationNameInput.value.trim() || `仿真-${new Date().toLocaleString()}`;

        if (!envParamId) {
            alert("请填写 env_param_id");
            return;
        }

        const payload = {
            env_param_id: Number(envParamId),
            name: name
        };

        try {
            const resp = await fetch('http://localhost:8081/simulation', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload)
            });

            const json = await resp.json();

            if (json.code === 200 && json.data) {
                const simulationId = json.data.simulation_id;
                createResultDiv.innerText = `创建成功，simulation_id: ${simulationId}`;
                simulationIdInput.value = simulationId;
                statusDiv.innerText = "";
            } else {
                createResultDiv.innerText = `创建失败: ${json.msg || '未知错误'}`;
            }
        } catch (err) {
            createResultDiv.innerText = `请求错误: ${err.message}`;
        }
    };

    let socket = null;

    startSimulationBtn.onclick = () => {
        const envParamId = envParamIdInput.value.trim();
        const simulationId = simulationIdInput.value.trim();
        const simulationType = strategySelect.value;

        if (!envParamId || !simulationId) {
            alert('请先输入有效的 env_param_id 和 simulation_id');
            return;
        }

        const wsUrl = `ws://localhost:8081/simulation/start_simulation?env_param_id=${envParamId}&simulation_id=${simulationId}`;
        socket = new WebSocket(wsUrl);

        statusDiv.innerText = `策略 ${simulationType}：连接中...`;

        socket.onopen = () => {
            statusDiv.innerText = `策略 ${simulationType}：WebSocket 连接已打开，仿真开始运行...`;
        };

        socket.onmessage = (event) => {
            try {
                const msg = JSON.parse(event.data);
                const type = msg.simulation_type;
                const sim = msg.simulation_result;

                console.log("Simulation type:", type);
                console.log("Received simulation data:", sim);


                if (!type || !sim) return;

                ensureDatasets(type);

                const timeLabel = sim.time_point ? new Date(sim.time_point).toLocaleTimeString() : `Hour ${simulationChart.data.labels.length + 1}`;
                if (!simulationChart.data.labels.includes(timeLabel)) {
                    simulationChart.data.labels.push(timeLabel);
                }

                const indexOffset = simulationChart.data.datasets.findIndex(ds => ds.label === `${strategyConfig[type].labelPrefix} Battery Energy`);
                if (indexOffset !== -1) {
                    simulationChart.data.datasets[indexOffset].data.push(Number(sim.battery_energy));
                    simulationChart.data.datasets[indexOffset + 1].data.push(Number(sim.grid_power));
                    simulationChart.data.datasets[indexOffset + 2].data.push(Number(sim.solar_power));
                    simulationChart.update();
                }

                if (msg.status === "completed") {
                    statusDiv.innerText = `策略 ${type}：仿真完成！`;
                    socket.close();
                } else if (msg.error) {
                    statusDiv.innerText = `策略 ${type}：错误 - ${msg.error}`;
                }
            } catch (e) {
                console.error("解析 WebSocket 数据异常:", e);
            }
        };

        socket.onerror = (event) => {
            statusDiv.innerText = `策略 ${simulationType}：WebSocket 连接错误`;
            console.error(event);
        };

        socket.onclose = () => {
            statusDiv.innerText += ` 策略 ${simulationType} 连接已关闭`;
        };
    };
</script>
</body>
</html>
